if not (type(OneRingLib) == "table" and type(OneRingLib.CreateRing) == "function") then
	return;
end

local function generateColor(c, n)
	local hue, v, s = (15+(c-1)*360/n)%360, 1, 0.85;

	local h = floor(hue/60) % 6;
	local f = (hue/60) % 1;
	local p, q, t = v - v * s, v - v * f * s, v - v*s + v * f * s;
	if h == 0 then return v, t, p;
	elseif h == 1 then return q, v, p;
	elseif h == 2 then return p, v, t;
	elseif h == 3 then return p, q, v;
	elseif h == 4 then return t, p, v;
	elseif h == 5 then return v, p, q;
	end
end

do -- OPieTrinkets
	OneRingLib:CreateRing("OPieTrinkets", {
		{"item", (GetInventorySlotInfo("Trinket0Slot")), r=0.05, g=0.75, b=0.95}, -- top
		{"item", (GetInventorySlotInfo("Trinket1Slot")), r=0.95, g=0.75, b=0.05}, -- bottom
		name="Trinkets"
	});
end
do -- OPieRaidSymbols
	local rname, rdesc = "OPieRaidSymbols", {
		{"func", r=1, g=1, b=0}, -- yellow star
		{"func", r=1, g=0.5, b=0.05}, -- orange circle
		{"func", r=1, g=0.30, b=1}, -- purple diamond
		{"func", r=0.20, g=1, b=0.20}, -- green triangle
		{"func", r=0.65, g=0.84, b=1}, -- silver moon
		{"func", r=0.20, g=0.20, b=1}, -- blue square
		{"func", r=1, g=0.10, b=0.10}, -- red cross
		{"func", r=0.74, g=0.70, b=0.60}, -- white skull
		name="Raid Markers", hotkey="ALT-R"
	};
	local function ringClick(ring, id)
		if GetRaidTargetIndex("target") == id then id = 0; end
		SetRaidTarget("target", id);
	end
	for i=1,8 do
		rdesc[i][2], rdesc[i][3], rdesc[i].icon = ringClick, i, "Interface\\TargetingFrame\\UI-RaidTargetingIcon_" .. i;
	end
	OneRingLib:CreateRing(rname, rdesc);
end
do -- OPieTracker
	local rname, rdesc = "OPieTracker", {
		name="Tracking", hotkey="ALT-F"
	};
	local function setTracking(ring, id)
		local name, tex = GetTrackingInfo(id);
		SetTracking(tex ~= GetTrackingTexture() and id or nil);
	end
	local function actionHint(etype, earg, eid)
		local name, tex = GetTrackingInfo(eid);
		return name and true or false, 0, tex, name, 0;
	end
	function rdesc.preClick(rid)
		local n = GetNumTrackingTypes();
		if n ~= #rdesc then
			for i=1,n do
				rdesc[i] = rdesc[i] or {}; local t = rdesc[i];
				t[1], t[2], t[3], t.actionHint = "func", setTracking, i, actionHint;
				t.r, t.g, t.b = generateColor(i,n);
			end
			for i=n+1,#rdesc do
				rdesc[i] = nil;
			end
			OneRingLib:SetRingData(rid, rdesc);
		end
	end
	local ringID = OneRingLib:CreateRing(rname, rdesc);
	EC_Register("PLAYER_REGEN_DISABLED", "OPie.AutoTracker", function()
		rdesc.preClick(ringID);
		return "remove";
	end);
end
do -- OPieAutoQuest
	local blacklist, whitelist, inring = {[32757]=true}, OneRingLib:RegisterPVar("AutoQuestWhitelist"), {};
	local rname, rdesc, rid = "OPieAutoQuest", {
		name="Quest Items", hotkey="ALT-Q", fastClickSlice=0, fastClickUpdate=true
	};
	rid = OneRingLib:CreateRing(rname, rdesc);

	local itypeQuest, lastQEvent = nil, 0;
	local function isActiveQuestItem(iid, popwhitelist)
		local _, link, _, _, _, iType = GetItemInfo(iid);
		local iid = tonumber(link:match("|Hitem:(%d+)"));
		itypeQuest = itypeQuest or select(6,GetItemInfo(28455)) or "Quest";

		if (GetTime()-lastQEvent) < 1 and iType ~= itypeQuest and popwhitelist then
			-- Item received in shortly after starting a quest; add it just in case.
			whitelist[iid] = true;
		end
		return iid and (iType == itypeQuest or whitelist[iid]) and GetItemSpell(iid) and not blacklist[iid];
	end
	local function scanInventory()
		-- Clear the existing ring, we're rescanning from inventory.
		for i=1,#rdesc do rdesc[i] = nil; end
		for k in pairs(inring) do inring[k] = nil; end

		for bag=0,4 do
			for slot=1,GetContainerNumSlots(bag) do
				local link = GetContainerItemLink(bag, slot);
				local iid = link and tonumber(link:match("item:(%d+)"));
				if link and isActiveQuestItem(link) and not inring[iid] then
					rdesc[#rdesc+1], inring[iid] = {"item", link:match("item:%d+")}, true;
				end
			end
		end
	end
	local function syncRing()
		local n = #rdesc;
		for i, d in ipairs(rdesc) do
			d.r, d.g, d.b = generateColor(i, n);
		end
		OneRingLib:SetRingData(rid, rdesc);
	end
	function rdesc.preClick(ring, id, force)
		if scanInventory then
			scanInventory();
			scanInventory = nil;
		else
			local i, changed = 1, force or false;
			while rdesc[i] do
				local iid = tonumber(rdesc[i][2]:match("item:(%d+)"));
				if GetItemCount(iid) == 0 then
					whitelist[iid], inring[iid], changed = nil, nil, true;
					table.remove(rdesc,i);
				else
					i = i + 1;
				end
			end
			if not changed then return; end
		end
		syncRing();
	end
	EC_Register("QUEST_FINISHED", "OPie.AutoQuest", function(e)
		-- Finished talking to a quest NPC, NOT finished a quest.
		lastQEvent = GetTime();
	end);
	EC_Register("CHAT_MSG_LOOT", "OPie.AutoQuest", function(e, text)
		local iid = tonumber(text:match("|Hitem:(%d+)"));
		if isActiveQuestItem(iid, true) and not inring[iid] then
			rdesc[#rdesc+1], inring[iid] = {"item", "item:" .. iid}, true;
			syncRing();
		end
	end);
	EC_Register("PLAYER_ENTERING_WORLD", "OPie.AutoQuest", function()
		for k, i in ipairs({9570, 29331, 28455}) do
			itypeQuest = select(6, GetItemInfo(i));
			if itypeQuest then return; end
		end
		GameTooltip:SetOwner(UIParent, "ANCHOR_NONE")
		GameTooltip:SetHyperlink("item:28455");
		GameTooltip:Hide();
		return "remove";
	end);
	EC_Register("PLAYER_REGEN_DISABLED", "OPie.AutoQuest", function()
		if scanInventory then
			scanInventory();
			syncRing();
		end
		return "remove";
	end);
end